home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / share / gtk-2.0 / demo / editable_cells.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-04-25  |  10.9 KB  |  391 lines

  1. /* Tree View/Editable Cells
  2.  *
  3.  * This demo demonstrates the use of editable cells in a GtkTreeView. If
  4.  * you're new to the GtkTreeView widgets and associates, look into
  5.  * the GtkListStore example first. It also shows how to use the
  6.  * GtkCellRenderer::editing-started signal to do custom setup of the
  7.  * editable widget.
  8.  *
  9.  * The cell renderers used in this demo are GtkCellRendererText, 
  10.  * GtkCellRendererCombo and GtkCellRendererProgress.
  11.  */
  12.  
  13. #include <gtk/gtk.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16.  
  17. static GtkWidget *window = NULL;
  18.  
  19. typedef struct
  20. {
  21.   gint   number;
  22.   gchar *product;
  23.   gint   yummy;
  24. }
  25. Item;
  26.  
  27. enum
  28. {
  29.   COLUMN_ITEM_NUMBER,
  30.   COLUMN_ITEM_PRODUCT,
  31.   COLUMN_ITEM_YUMMY,
  32.   NUM_ITEM_COLUMNS
  33. };
  34.  
  35. enum
  36. {
  37.   COLUMN_NUMBER_TEXT,
  38.   NUM_NUMBER_COLUMNS
  39. };
  40.  
  41. static GArray *articles = NULL;
  42.  
  43. static void
  44. add_items (void)
  45. {
  46.   Item foo;
  47.  
  48.   g_return_if_fail (articles != NULL);
  49.  
  50.   foo.number = 3;
  51.   foo.product = g_strdup ("bottles of coke");
  52.   foo.yummy = 20;
  53.   g_array_append_vals (articles, &foo, 1);
  54.  
  55.   foo.number = 5;
  56.   foo.product = g_strdup ("packages of noodles");
  57.   foo.yummy = 50;
  58.   g_array_append_vals (articles, &foo, 1);
  59.  
  60.   foo.number = 2;
  61.   foo.product = g_strdup ("packages of chocolate chip cookies");
  62.   foo.yummy = 90;
  63.   g_array_append_vals (articles, &foo, 1);
  64.  
  65.   foo.number = 1;
  66.   foo.product = g_strdup ("can vanilla ice cream");
  67.   foo.yummy = 60;
  68.   g_array_append_vals (articles, &foo, 1);
  69.  
  70.   foo.number = 6;
  71.   foo.product = g_strdup ("eggs");
  72.   foo.yummy = 10;
  73.   g_array_append_vals (articles, &foo, 1);
  74. }
  75.  
  76. static GtkTreeModel *
  77. create_items_model (void)
  78. {
  79.   gint i = 0;
  80.   GtkListStore *model;
  81.   GtkTreeIter iter;
  82.  
  83.   /* create array */
  84.   articles = g_array_sized_new (FALSE, FALSE, sizeof (Item), 1);
  85.  
  86.   add_items ();
  87.  
  88.   /* create list store */
  89.   model = gtk_list_store_new (NUM_ITEM_COLUMNS, G_TYPE_INT, G_TYPE_STRING,
  90.                               G_TYPE_INT, G_TYPE_BOOLEAN);
  91.  
  92.   /* add items */
  93.   for (i = 0; i < articles->len; i++)
  94.     {
  95.       gtk_list_store_append (model, &iter);
  96.  
  97.       gtk_list_store_set (model, &iter,
  98.                           COLUMN_ITEM_NUMBER,
  99.                           g_array_index (articles, Item, i).number,
  100.                           COLUMN_ITEM_PRODUCT,
  101.                           g_array_index (articles, Item, i).product,
  102.                           COLUMN_ITEM_YUMMY,
  103.                           g_array_index (articles, Item, i).yummy,
  104.                           -1);
  105.     }
  106.  
  107.   return GTK_TREE_MODEL (model);
  108. }
  109.  
  110. static GtkTreeModel *
  111. create_numbers_model (void)
  112. {
  113. #define N_NUMBERS 10
  114.   gint i = 0;
  115.   GtkListStore *model;
  116.   GtkTreeIter iter;
  117.  
  118.   /* create list store */
  119.   model = gtk_list_store_new (NUM_NUMBER_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
  120.  
  121.   /* add numbers */
  122.   for (i = 0; i < N_NUMBERS; i++)
  123.     {
  124.       char str[2] = { '0' + i, '\0' };
  125.  
  126.       gtk_list_store_append (model, &iter);
  127.  
  128.       gtk_list_store_set (model, &iter,
  129.                           COLUMN_NUMBER_TEXT, str,
  130.                           -1);
  131.     }
  132.  
  133.   return GTK_TREE_MODEL (model);
  134.  
  135. #undef N_NUMBERS
  136. }
  137.  
  138. static void
  139. add_item (GtkWidget *button, gpointer data)
  140. {
  141.   Item foo;
  142.   GtkTreeIter iter;
  143.   GtkTreeModel *model = (GtkTreeModel *)data;
  144.  
  145.   g_return_if_fail (articles != NULL);
  146.  
  147.   foo.number = 0;
  148.   foo.product = g_strdup ("Description here");
  149.   foo.yummy = 50;
  150.   g_array_append_vals (articles, &foo, 1);
  151.  
  152.   gtk_list_store_append (GTK_LIST_STORE (model), &iter);
  153.   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
  154.                       COLUMN_ITEM_NUMBER, foo.number,
  155.                       COLUMN_ITEM_PRODUCT, foo.product,
  156.                       COLUMN_ITEM_YUMMY, foo.yummy,
  157.                       -1);
  158. }
  159.  
  160. static void
  161. remove_item (GtkWidget *widget, gpointer data)
  162. {
  163.   GtkTreeIter iter;
  164.   GtkTreeView *treeview = (GtkTreeView *)data;
  165.   GtkTreeModel *model = gtk_tree_view_get_model (treeview);
  166.   GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
  167.  
  168.   if (gtk_tree_selection_get_selected (selection, NULL, &iter))
  169.     {
  170.       gint i;
  171.       GtkTreePath *path;
  172.  
  173.       path = gtk_tree_model_get_path (model, &iter);
  174.       i = gtk_tree_path_get_indices (path)[0];
  175.       gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
  176.  
  177.       g_array_remove_index (articles, i);
  178.  
  179.       gtk_tree_path_free (path);
  180.     }
  181. }
  182.  
  183. static gboolean
  184. separator_row (GtkTreeModel *model,
  185.                GtkTreeIter  *iter,
  186.                gpointer      data)
  187. {
  188.   GtkTreePath *path;
  189.   gint idx;
  190.  
  191.   path = gtk_tree_model_get_path (model, iter);
  192.   idx = gtk_tree_path_get_indices (path)[0];
  193.  
  194.   gtk_tree_path_free (path);
  195.  
  196.   return idx == 5;
  197. }
  198.  
  199. static void
  200. editing_started (GtkCellRenderer *cell,
  201.                  GtkCellEditable *editable,
  202.                  const gchar     *path,
  203.                  gpointer         data)
  204. {
  205.   gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (editable), 
  206.                                         separator_row, NULL, NULL);
  207. }
  208.  
  209. static void
  210. cell_edited (GtkCellRendererText *cell,
  211.              const gchar         *path_string,
  212.              const gchar         *new_text,
  213.              gpointer             data)
  214. {
  215.   GtkTreeModel *model = (GtkTreeModel *)data;
  216.   GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
  217.   GtkTreeIter iter;
  218.  
  219.   gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell), "column"));
  220.  
  221.   gtk_tree_model_get_iter (model, &iter, path);
  222.  
  223.   switch (column)
  224.     {
  225.     case COLUMN_ITEM_NUMBER:
  226.       {
  227.         gint i;
  228.  
  229.         i = gtk_tree_path_get_indices (path)[0];
  230.         g_array_index (articles, Item, i).number = atoi (new_text);
  231.  
  232.         gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
  233.                             g_array_index (articles, Item, i).number, -1);
  234.       }
  235.       break;
  236.  
  237.     case COLUMN_ITEM_PRODUCT:
  238.       {
  239.         gint i;
  240.         gchar *old_text;
  241.  
  242.         gtk_tree_model_get (model, &iter, column, &old_text, -1);
  243.         g_free (old_text);
  244.  
  245.         i = gtk_tree_path_get_indices (path)[0];
  246.         g_free (g_array_index (articles, Item, i).product);
  247.         g_array_index (articles, Item, i).product = g_strdup (new_text);
  248.  
  249.         gtk_list_store_set (GTK_LIST_STORE (model), &iter, column,
  250.                             g_array_index (articles, Item, i).product, -1);
  251.       }
  252.       break;
  253.     }
  254.  
  255.   gtk_tree_path_free (path);
  256. }
  257.  
  258. static void
  259. add_columns (GtkTreeView  *treeview, 
  260.              GtkTreeModel *items_model,
  261.              GtkTreeModel *numbers_model)
  262. {
  263.   GtkCellRenderer *renderer;
  264.  
  265.   /* number column */
  266.   renderer = gtk_cell_renderer_combo_new ();
  267.   g_object_set (renderer,
  268.                 "model", numbers_model,
  269.                 "text-column", COLUMN_NUMBER_TEXT,
  270.                 "has-entry", FALSE,
  271.                 "editable", TRUE,
  272.                 NULL);
  273.   g_signal_connect (renderer, "edited",
  274.                     G_CALLBACK (cell_edited), items_model);
  275.   g_signal_connect (renderer, "editing-started",
  276.                     G_CALLBACK (editing_started), NULL);
  277.   g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (COLUMN_ITEM_NUMBER));
  278.  
  279.   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
  280.                                                -1, "Number", renderer,
  281.                                                "text", COLUMN_ITEM_NUMBER,
  282.                                                NULL);
  283.  
  284.   /* product column */
  285.   renderer = gtk_cell_renderer_text_new ();
  286.   g_object_set (renderer,
  287.                 "editable", TRUE,
  288.                 NULL);
  289.   g_signal_connect (renderer, "edited",
  290.                     G_CALLBACK (cell_edited), items_model);
  291.   g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (COLUMN_ITEM_PRODUCT));
  292.  
  293.   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
  294.                                                -1, "Product", renderer,
  295.                                                "text", COLUMN_ITEM_PRODUCT,
  296.                                                NULL);
  297.  
  298.   /* yummy column */
  299.   renderer = gtk_cell_renderer_progress_new ();
  300.   g_object_set_data (G_OBJECT (renderer), "column", GINT_TO_POINTER (COLUMN_ITEM_YUMMY));
  301.  
  302.   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
  303.                                                -1, "Yummy", renderer,
  304.                                                "value", COLUMN_ITEM_YUMMY,
  305.                                                NULL);
  306.   
  307.  
  308. }
  309.  
  310. GtkWidget *
  311. do_editable_cells (GtkWidget *do_widget)
  312. {
  313.   if (!window)
  314.     {
  315.       GtkWidget *vbox;
  316.       GtkWidget *hbox;
  317.       GtkWidget *sw;
  318.       GtkWidget *treeview;
  319.       GtkWidget *button;
  320.       GtkTreeModel *items_model;
  321.       GtkTreeModel *numbers_model;
  322.  
  323.       /* create window, etc */
  324.       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  325.       gtk_window_set_screen (GTK_WINDOW (window),
  326.                              gtk_widget_get_screen (do_widget));
  327.       gtk_window_set_title (GTK_WINDOW (window), "Shopping list");
  328.       gtk_container_set_border_width (GTK_CONTAINER (window), 5);
  329.       g_signal_connect (window, "destroy",
  330.                         G_CALLBACK (gtk_widget_destroyed), &window);
  331.  
  332.       vbox = gtk_vbox_new (FALSE, 5);
  333.       gtk_container_add (GTK_CONTAINER (window), vbox);
  334.  
  335.       gtk_box_pack_start (GTK_BOX (vbox),
  336.                           gtk_label_new ("Shopping list (you can edit the cells!)"),
  337.                           FALSE, FALSE, 0);
  338.  
  339.       sw = gtk_scrolled_window_new (NULL, NULL);
  340.       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
  341.                                            GTK_SHADOW_ETCHED_IN);
  342.       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
  343.                                       GTK_POLICY_AUTOMATIC,
  344.                                       GTK_POLICY_AUTOMATIC);
  345.       gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
  346.  
  347.       /* create models */
  348.       items_model = create_items_model ();
  349.       numbers_model = create_numbers_model ();
  350.  
  351.       /* create tree view */
  352.       treeview = gtk_tree_view_new_with_model (items_model);
  353.       gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
  354.       gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
  355.                                    GTK_SELECTION_SINGLE);
  356.  
  357.       add_columns (GTK_TREE_VIEW (treeview), items_model, numbers_model);
  358.  
  359.       g_object_unref (numbers_model);
  360.       g_object_unref (items_model);
  361.  
  362.       gtk_container_add (GTK_CONTAINER (sw), treeview);
  363.  
  364.       /* some buttons */
  365.       hbox = gtk_hbox_new (TRUE, 4);
  366.       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  367.  
  368.       button = gtk_button_new_with_label ("Add item");
  369.       g_signal_connect (button, "clicked",
  370.                         G_CALLBACK (add_item), items_model);
  371.       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  372.  
  373.       button = gtk_button_new_with_label ("Remove item");
  374.       g_signal_connect (button, "clicked",
  375.                         G_CALLBACK (remove_item), treeview);
  376.       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  377.  
  378.       gtk_window_set_default_size (GTK_WINDOW (window), 320, 200);
  379.     }
  380.  
  381.   if (!GTK_WIDGET_VISIBLE (window))
  382.     gtk_widget_show_all (window);
  383.   else
  384.     {
  385.       gtk_widget_destroy (window);
  386.       window = NULL;
  387.     }
  388.  
  389.   return window;
  390. }
  391.